// 主要实现用户服务子服务的服务器的搭建
#include "user_server.hpp"

// 引入命令行标志解析库
#include <gflags/gflags.h>

// 定义命令行标志
DEFINE_bool(run_mode, false, "程序的运行模式，false-调试； true-发布；");
DEFINE_string(log_file, "", "发布模式下，用于指定日志的输出文件");
DEFINE_int32(log_level, 0, "发布模式下，用于指定日志输出等级");

DEFINE_string(registry_host, "http://127.0.0.1:2379", "服务注册中心地址");
DEFINE_string(instance_name, "/user_service/instance", "当前实例名称");
DEFINE_string(access_host, "127.0.0.1:10003", "当前实例的外部访问地址");

DEFINE_int32(listen_port, 10003, "RPC服务器监听端口");
DEFINE_int32(rpc_timeout, -1, "RPC调用超时时间（秒），-1表示无限等待");
DEFINE_int32(rpc_threads, 1, "RPC的IO线程数量");

DEFINE_string(base_service, "/service", "服务监控根目录");
DEFINE_string(file_service, "/service/file_service", "文件管理子服务名称");

DEFINE_string(es_host, "http://127.0.0.1:9200/", "Elasticsearch搜索引擎服务器URL");

DEFINE_string(mysql_host, "127.0.0.1", "MySQL服务器访问地址");
DEFINE_string(mysql_user, "root", "MySQL服务器访问用户名");
DEFINE_string(mysql_pswd, "123456", "MySQL服务器访问密码");
DEFINE_string(mysql_db, "mag", "MySQL默认库名称");
DEFINE_string(mysql_cset, "utf8", "MySQL客户端字符集");
DEFINE_int32(mysql_port, 0, "MySQL服务器访问端口");
DEFINE_int32(mysql_pool_count, 4, "MySQL连接池最大连接数量");

DEFINE_string(redis_host, "127.0.0.1", "Redis服务器访问地址");
DEFINE_int32(redis_port, 6379, "Redis服务器访问端口");
DEFINE_int32(redis_db, 0, "Redis默认库号");
DEFINE_bool(redis_keep_alive, true, "Redis长连接保活选项");

DEFINE_string(dms_key_id, "LTAI5tH9F7MS2kVPQtkfv9Ka", "短信平台秘钥ID");
DEFINE_string(dms_key_secret, "wXq2J3l9DEGQFbENrOwRMEl3QtqbiZ", "短信平台秘钥");

// 主函数
int main(int argc, char *argv[])
{
    // 解析命令行参数
    google::ParseCommandLineFlags(&argc, &argv, true);

    // 初始化日志系统
    init_logger(FLAGS_run_mode, FLAGS_log_file, FLAGS_log_level);
    LOG_INFO("日志系统初始化完成，运行模式: {}, 日志文件: {}, 日志级别: {}", 
             FLAGS_run_mode ? "发布" : "调试", 
             FLAGS_log_file.empty() ? "标准输出" : FLAGS_log_file, 
             FLAGS_log_level);

    // 创建 UserServerBuilder 实例，构建和配置UserServer服务
    mag::UserServerBuilder usb;

    // 配置各个组件
    try {
        // 配置短信服务客户端（DMS）
        usb.make_dms_object(FLAGS_dms_key_id, FLAGS_dms_key_secret);
        LOG_INFO("短信服务客户端配置完成。");

        // 配置 Elasticsearch 客户端
        usb.make_es_object({FLAGS_es_host});
        LOG_INFO("Elasticsearch 客户端配置完成，主机: {}", FLAGS_es_host);

        // 配置 MySQL 客户端，支持连接池
        usb.make_mysql_object(
            FLAGS_mysql_user, 
            FLAGS_mysql_pswd, 
            FLAGS_mysql_host, 
            FLAGS_mysql_db, 
            FLAGS_mysql_cset, 
            FLAGS_mysql_port, 
            FLAGS_mysql_pool_count
        );
        LOG_INFO("MySQL 客户端配置完成，主机: {}, 端口: {}, 数据库: {}", 
                 FLAGS_mysql_host, FLAGS_mysql_port, FLAGS_mysql_db);

        // 配置 Redis 客户端
        usb.make_redis_object(
            FLAGS_redis_host, 
            FLAGS_redis_port, 
            FLAGS_redis_db, 
            FLAGS_redis_keep_alive
        );
        LOG_INFO("Redis 客户端配置完成，主机: {}, 端口: {}, 数据库: {}, 保持连接: {}", 
                 FLAGS_redis_host, FLAGS_redis_port, FLAGS_redis_db, 
                 FLAGS_redis_keep_alive ? "是" : "否");

        // 配置服务发现客户端，并设置文件服务名称及信道管理回调
        usb.make_discovery_object(
            FLAGS_registry_host, 
            FLAGS_base_service, 
            FLAGS_file_service
        );
        LOG_INFO("服务发现客户端配置完成，注册中心: {}, 基础服务: {}, 文件服务: {}", 
                 FLAGS_registry_host, FLAGS_base_service, FLAGS_file_service);

        // 配置 RPC 服务器并添加服务
        usb.make_rpc_server(
            FLAGS_listen_port, 
            FLAGS_rpc_timeout, 
            FLAGS_rpc_threads
        );
        LOG_INFO("RPC 服务器配置完成，监听端口: {}", FLAGS_listen_port);

        // 注册服务到注册中心
        std::string service_full_name = FLAGS_base_service + FLAGS_instance_name;
        /// 注册中心地址、服务的完整名称、服务的访问地址
        usb.make_registry_object(
            FLAGS_registry_host, 
            service_full_name, 
            FLAGS_access_host
        );
        LOG_INFO("服务已注册到注册中心，服务名称: {}, 访问地址: {}", 
                 service_full_name, FLAGS_access_host);
    }
    catch (const std::exception &e) {
        LOG_FATAL("配置过程中发生异常: {}", e.what());
        return EXIT_FAILURE;
    }
    catch (...) {
        LOG_FATAL("配置过程中发生未知异常！");
        return EXIT_FAILURE;
    }

    // 构建 UserServer 实例
    auto server = usb.build();
    LOG_INFO("UserServer 实例构建完成，准备启动。");

    // 启动服务器
    try {
        server->start();
        LOG_INFO("服务器已启动，正在运行。");
    }
    catch (const std::exception &e) {
        LOG_FATAL("服务器启动过程中发生异常: {}", e.what());
        return EXIT_FAILURE;
    }
    catch (...) {
        LOG_FATAL("服务器启动过程中发生未知异常！");
        return EXIT_FAILURE;
    }

    return EXIT_SUCCESS;
}
